#include "CommandVariable.h"

CommandVariable* CommandVariable::find_variable( char *var_name )
{
	CommandVariable::CVar* var;

	for ( var = cvar_vars; var ; var = var->next )
	{
		if ( !strcmp( var_name, var->name ))
			return var;
	}
	return NULL;
}

float CommandVarible::get_value( char* var_name )
{
	CommandVariable::CVar *cvar;

	var = find_variable( var_name );
	if ( !var )
		return 0;

	return atof( var->string );
}

float CommandVarible::get_string( char* var_name )
{
	CommandVariable::CVar *cvar;

	var = find_variable( var_name );
	if ( !var )
		return "";

	return var->string;
}

char* CommandVariable::complete_variable( char* partial )
{
	CommandVariable::CVar* cvar;
	int len;

	len = strlen( partial );

	if ( !len )
		return NULL;

	// check exact match
	for ( cvar = cvar_vars; cvar ; cvar = cvar->next )
		if ( !strcmp( partial, cvar->name ) )
			return cvar->name;

	// check partial match
	for ( cvar = cvar_vars; cvar ; cvar = cvar->next )
		if ( !strncmp( partial, cvar->name, len ) )
			return cvar->name;

	return NULL;
}

CommandVariable* CommandVariable::get( char *var_name, char* var_value, int flags )
{
	CommandVariable::CVar* var;

	if ( flags & ( CVAR_USERINFO  ) )
	{
		if ( !info_validate( var_name ) )
		{
			printf( " invalid info cvar name \n" );
			return NULL;
		}
	}

	var = find_variable( var_name );
	if ( var )
	{
		var->flags |= flags;
		return var;
	}
	
	if ( !var_value )
		return NULL;

	if ( flags & ( CVAR_USERINFO ) )
	{
		if ( !info_validate ( var_value ) )
		{
			printf( "invalid infor cvar value\n" );
			return NULL;
		}
	}
	var = Memory::malloc( *var );
	var->name = copy_string( var_name );
	var->string = copy_string( var_value );
	var->modified = true;
	var->value = atof( var->string );

	// link the variable in
	var->next = cvar_vars;
	cvar_vars = var;

	var->flags = flags;

	return var;
}

CommandVariable* CommandVariable::set2( char* var_name, char* value, bool force )
{
	CommandVariable::CVar* var;

	var = find_variable( var_name );
	if ( !var )
	{
		// create it
		return get( var_name, value, 0 );
	}

	if ( var->flags & ( CVAR_USERINFO ) )
	{
		if ( !info_validate( var_name ) )
		{
			printf( "invalid info char value\n" );
			return var;
		}
	}

	if ( !force )
	{
		if ( var->flags & CVAR_NOSET )
		{
			printf( "%s is write protected.\n", var_name );
			return var;
		}

		if ( var->flags & CVAR_LATCH )
		{
			if ( var->latched_string )
			{
				if ( strcmp( value, var->latched_string ) == 0 )
					return var;
			}
			else
			{
				if ( strcmp( value, var->string ) == 0 )
					return var;
			}

			return var;
		}
	}
	else
	{
		if ( var->latched_string )
		{
			Memory::Free( var->latched_string );
			var->latched_string = NULL;
		}
	}

	if ( !strcmp( value, var->string ) )
		return var;

	var->modified = true;

	if ( var->flags & CVAR_USERINFO )
		userinfo_modified = true;

	Memory::Free( var->string );

	var->string = copy_string( value );
	var->value = atof( var->string );

	return var;
}


CommandVariable* CommandVariable::force_set( char* var_name, char* value )
{
	return set2( var_name, value, true );
}

CommandVariable* CommandVariable::full_set( char* var_name, char* value, int flags )
{
	CommandVariable::CVar* cvar;
	var = find_variable( var_name );
	if ( !var )
	{
		// create it
		return cvar_get( var_name, value, flags );
	}

	var->modified = true;

	if ( var->flags & ( CVAR_USERINFO ) )
		userinfo_modified = true;

	Memory::Free( var->string );

	var->string = copy_string( value );
	var->value  = atof( var->string );
	var->flags  = flags;

	return var;
}

void CommandVariable::setvalue( char* var_name, float value )
{
	char val[32];

	if ( value == (int) value )
		sprintf( val, sizeof( val ), "%i", (int) value );
	else
		sprintf( val, sizeof( val ), "%f", value );
	cvar_set( var_name, val );
}


void CommandVariable::write_variables( char *path )
{
	CommandVariable::CVar* var;
	char buffer[1024];
	FILE *f;

	f = fopen( path, "a" );
	for ( var = cvar_vars; var ; var = var->next )
	{
		if ( var->flags & CVAR_ARCHIVE )
		{
			sprintf( buffer, sizeof(buffer), " set %s \"%s\"\n", var->name, var->string );
			fprintf( f, "%s", buffer );
		}
	}
	fclose(f);
}

char* CommandVariable::bit_info( int bit )
{
	static char info[MAX_INFO_STRING];
	CommandVariable::CVar* var;

	info[0] = 0;

	for ( var = cvar_vars; var ; var = var->next )
	{
		if ( var->flags & bit )
			setvalue_for_key( info, var->name, var->string );
	}
	return info;
}

char* CommandVariable::userinfo( void )
{
	return bit_info( CVAR_USERINFO );
}